package wizard;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

import fr.alma.interfacesPlugins.PluginSortie;

/**
 * Classe de generation du code java du plugin
 * @author KROMMENHOEK Cedric
 *
 */
public class GenerateurCode implements PluginSortie {

	/**
	 * Acces a la categorie du plugin.
	 * @return la categorie
	 */
	public String getCategorie() {
		return "wizard";
	}

	/**
	 * Acces a la description du plugin.
	 * @return la description
	 */
	public String getDescription() {
		return "Generation du code java du plugin";
	}

	/**
	 * Demarrage du plugin.
	 */
	public void start() {
		// Aucune action
	}

	/**
	 * Arret du plugin.
	 */
	public void stop() {
		// Aucune action
	}

	public void update(Object objet) {
		Properties proprietes = (Properties) objet;
		this.generationCode(proprietes);

	}

	private void generationCode(Properties proprietes) {
		String chemin = "src/plugins/java/" + proprietes.getProperty("package") + "/";
		String cheminFichier = chemin + proprietes.getProperty("nom") + ".java";
		File repertoire = new File(chemin);
		File fichier = new File(cheminFichier);
		try {
			repertoire.mkdirs();
			fichier.createNewFile();
			BufferedWriter flux = new BufferedWriter(new FileWriter(cheminFichier));
			String nomInterface = this.getNomInterface(proprietes.getProperty("type"));
			this.generationEntete(flux, proprietes.getProperty("package"), proprietes.getProperty("nom"), nomInterface);
			this.generationMethodesBase(flux, proprietes.getProperty("categorie"), proprietes.getProperty("description"));
			if (nomInterface.equals("PluginEntree")) {
				this.generationMethodesEntree(flux);
			} else if (nomInterface.equals("PluginSortie")) {
				this.generationMethodeSortie(flux);
			} else {
				this.generationMethodesEntree(flux);
				this.generationMethodeSortie(flux);
			}			
			this.generationPied(flux);
			flux.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private String getNomInterface(String type) {
		if (type.equals("entree")) {
			return "PluginEntree";
		} else if (type.equals("sortie")) {
			return "PluginSortie";
		} else {
			return "PluginTransformateur";
		}
	}
	
	private void generationEntete(BufferedWriter flux, String nomPackage, String nomPlugin, String nomInterface) throws IOException {
		flux.write("package " + nomPackage + ";\n");
		flux.newLine();
		
		flux.write("import fr.alma.interfacesPlugins." + nomInterface + ";\n");
		if (!nomInterface.equals("PluginSortie")) {
			flux.write(	"import fr.alma.observation.Observer;\n" +
						"import fr.alma.observation.Observateur;\n");
		}
		flux.newLine();
		
		flux.write(	"/**\n" +
					" * Classe de plugin generee automatiquement.\n" +
					" */\n");
		flux.write("public class " + nomPlugin + " implements " + nomInterface + " {\n");
		flux.newLine();		
		
		if (!nomInterface.equals("PluginSortie")) {
			flux.write( "\t/**\n" +
						"\t * Gestion des observateurs.\n" +
						"\t */\n");
			flux.write(	"\tprivate Observer observer;\n");
			flux.newLine();
		}
		
		flux.write(	"\t/**\n" +
					"\t * Constructeur.\n" +
					"\t */\n");
		flux.write(	"\tpublic " + nomPlugin + "() {\n");
		if (nomInterface.equals("PluginSortie")) {
			flux.newLine();
		} else {
			flux.write("\t\tthis.observer = new Observer();\n");
		}
		flux.write("\t}\n");
		flux.newLine();		
	}
	
	private void generationMethodesBase(BufferedWriter flux, String categorie, String description) throws IOException {
		flux.write( "\t/**\n" +
					"\t * Demarrage du plugin.\n" +
					"\t */\n");
		flux.write(	"\tpublic void start() {\n" +
					"\n" +
					"\t}\n");
		flux.newLine();
		
		flux.write( "\t/**\n" +
					"\t * Arret du plugin.\n" +
					"\t */\n");
		flux.write(	"\tpublic void stop() {\n" +
					"\n" +
					"\t}\n");
		flux.newLine();
		
		flux.write( "\t/**\n" +
					"\t * Methode d'acces a la categorie du plugin.\n" +
					"\t */\n");
		flux.write(	"\tpublic String getCategorie() {\n" +
					"\t\treturn \"" + categorie + "\";\n" +
					"\t}\n");
		flux.newLine();
		
		flux.write( "\t/**\n" +
					"\t * Methode d'acces a la description du plugin.\n" +
					"\t */\n");
		flux.write(	"\tpublic String getDescription() {\n" +
					"\t\treturn \"" + description + "\";\n" +
					"\t}\n");
		flux.newLine();
	}
	
	private void generationMethodesEntree(BufferedWriter flux) throws IOException {
		flux.write( "\t/**\n" +
					"\t * Methode d'acces au type de retour du plugin.\n" +
					"\t */\n");
		flux.write( "\tpublic Class<?> getReturnType() {\n" +
					"\t\treturn Object.class;\n" +
					"\t}\n");
		flux.newLine();
		
		flux.write( "\t/**\n" +
					"\t * Ajout d'un observateur au plugin.\n" +
					"\t * @param l'observateur a ajouter\n" +
					"\t */\n");
		flux.write( "\tpublic void ajoutObservateur(Observateur observateur) {\n" +
					"\t\tthis.observer.ajoutObservateur(observateur);\n" +
					"\t}\n");
		flux.newLine();
		
		flux.write( "\t/**\n" +
					"\t * Mise a jour des observateurs.\n" +
					"\t */\n");
		flux.write(	"\tpublic void updateObservateurs() {\n" +
					"\t\tthis.observer.updateObservateurs(null);\n" +
					"\t}\n");
		flux.newLine();
	}
	
	private void generationMethodeSortie(BufferedWriter flux) throws IOException {
		flux.write( "\t/**\n" +
					"\t * Mise a jour du plugin.\n" +
					"\t */\n");
		flux.write(	"\tpublic void update(Object objet) {\n" +
					"\n" +
					"\t}\n");
		flux.newLine();
	}
	
	private void generationPied(BufferedWriter flux) throws IOException {
		flux.write("}\n");
		flux.newLine();
	}
	
}
